package com.onlyxiahui.app.base.task;

import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 执行异步任务的队列线程
 * date 2014-09-12 2:17:36
 * @author XiaHui
 */

public class QueueTaskThread extends Thread {

	protected final Logger logger = LoggerFactory.getLogger(this.getClass());
	/**
	 * 任务队列
	 */
	private ConcurrentLinkedQueue<ExecuteTask> executeTaskQueue = new ConcurrentLinkedQueue<ExecuteTask>();
	/**
	 * 线程休眠时间
	 */
	private long sleepTime = 200;
	private ExecutorService pool;

	public QueueTaskThread() {
		this(10);
	}

	/**
	 * 指定线程数量的构造函数
	 * 
	 * @param poolCount
	 */
	public QueueTaskThread(int poolCount) {
		pool = new ThreadPoolExecutor(
				poolCount,
				poolCount,
                0L, 
                TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<Runnable>()
                );
		this.start();
	}

	/**
	 * 添加任务
	 * 
	 * @param executeTask
	 */
	public void add(ExecuteTask executeTask) {
		executeTaskQueue.add(executeTask);
	}

	@Override
	public void run() {
		while (true) {
			handleTask();// 处理任务
			threadSleep(sleepTime);
		}
	}

	private void threadSleep(long time) {
		try {
			sleep(time);
		} catch (InterruptedException e) {
			logger.error("", e);
		}
	}

	/**
	 * 处理任务队列，检查其中是否有任务
	 */
	private void handleTask() {
		ExecuteTask task;
		while (executeTaskQueue.peek() != null) {
			try {
				task = executeTaskQueue.poll();
				handleTask(task);
			} catch (Exception e) {
				logger.error("", e);
			}
		}
	}

	/**
	 * 执行任务操作
	 * 
	 * @param executeTask
	 */
	private void handleTask(final ExecuteTask executeTask) {
		pool.execute(new Runnable() {

			@Override
			public void run() {
				try {
					executeTask.execute();
				} catch (Exception e) {
					logger.error("", e);
				}
			}
		});
	}

	public void execute(final ExecuteTask task) {
		pool.execute(new Runnable() {

			@Override
			public void run() {
				try {
					task.execute();
				} catch (Exception e) {
					logger.error("", e);
				}
			}
		});
	}
}
